<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>IntersectionObserver Demo</title>
  <style>
    /* 容器样式，设置足够高度以便滚动 */
    .container {
      height: 1500px;
      padding: 20px;
    }

    /* 盒子基本样式，默认为浅蓝色 */
    .box {
      margin: 100px 0;
      height: 200px;
      background-color: lightblue;
    }

    /* 可见状态的样式，当元素进入视口时应用 */
    .is-visible {
      background-color: lightgreen;
    }
  </style>
</head>

<body>
  <div class="container">
    <!-- 三个测试盒子，用于观察滚动时的交叉状态变化 -->
    <div class="box" id="box1">Box 1</div>
    <div class="box" id="box2">Box 2</div>
    <div class="box" id="box3">Box 3</div>
  </div>
  <script>
    // 等待DOM完全加载后执行
    document.addEventListener('DOMContentLoaded', function () {
      // 获取所有class为box的元素
      const boxes = document.querySelectorAll('.box')

      // 配置IntersectionObserver的选项
      const observerOptions = {
        root: null, // root为null表示使用视口作为观察的参考框架
        rootMargin: '0px', // 视口边缘的扩展或收缩，类似CSS的margin
        threshold: 0.5, // 目标元素有50%进入视口时触发回调
      }

      // 定义观察者的回调函数，当被观察元素的可见性变化时调用
      const observerCallback = (entries, observer) => {
        // entries是IntersectionObserverEntry对象的数组，包含了所有被观察元素的交叉状态
        entries.forEach(entry => {
          // isIntersecting属性表示目标元素是否与视口相交
          if (entry.isIntersecting) {
            // 元素进入视口，添加可见类
            entry.target.classList.add('is-visible')
          } else {
            // 元素离开视口，移除可见类
            entry.target.classList.remove('is-visible')
          }
        })
      }

      // 创建IntersectionObserver实例，传入回调函数和配置选项
      const observer = new IntersectionObserver(
        observerCallback,
        observerOptions
      )

      // 开始观察所有box元素
      boxes.forEach(box => observer.observe(box))
      
      // 注意：当不再需要观察时，可以调用observer.disconnect()来停止所有观察
    })
  </script>
</body>

</html>